#pragma once

//// today: fixed point gouraud shading
//// today: floating point texture mapping

//// today: if late, z-buffer

namespace krryn{
namespace system_imp{
	template<typename _Description>
	class scan_convert{
	public:
		typedef typename _Description::vertex_type vertex_type;

		bool m_IsLeftSide;

		float m_Dx;
		float m_Dr;
		float m_Dg;
		float m_Db;

		float m_X;
		float m_R;
		float m_G;
		float m_B;

		void recalculate_slopes(const scan_convert &a_Scan, float a_DeltaInv){
			//m_Dx = (a_Scan.m_X - m_X) * a_DeltaInv;

			if(_Description::m_HasColor){
				m_Dr = (a_Scan.m_R - m_R) * a_DeltaInv;
				m_Dg = (a_Scan.m_G - m_G) * a_DeltaInv;
				m_Db = (a_Scan.m_B - m_B) * a_DeltaInv;
			}
		}

		void init_edge(const vertex_type &a_Top, const vertex_type &a_Bottom, float a_DeltaInv){
			m_Dx = (a_Top.get_position().m_X - a_Bottom.get_position().m_X) * a_DeltaInv;
			m_X = a_Bottom.get_position().m_X;

			if(_Description::m_HasColor){
				m_Dr = (a_Top.get_color().m_R - a_Bottom.get_color().m_R) * a_DeltaInv;
				m_Dg = (a_Top.get_color().m_G - a_Bottom.get_color().m_G) * a_DeltaInv;
				m_Db = (a_Top.get_color().m_B - a_Bottom.get_color().m_B) * a_DeltaInv;

				m_R = a_Bottom.get_color().m_R;
				m_G = a_Bottom.get_color().m_G;
				m_B = a_Bottom.get_color().m_B;
			}
		}

		/// correct for sub-pixel accuracy
		void sub_pixel(float a_Subpixel){
			m_X += m_Dx * a_Subpixel;

			if(_Description::m_HasColor){
				m_R += m_Dr * a_Subpixel;
				m_G += m_Dg * a_Subpixel;
				m_B += m_Db * a_Subpixel;
			}
		}

		/// interpolate the values using the deltas calculated previously
		void interpolate(){
			m_X += m_Dx;

			if(_Description::m_HasColor){
				m_R += m_Dr;
				m_G += m_Dg;
				m_B += m_Db;
			}
		}

		/// skip ahead till we're at a correct offset again
		/// (needed due to rounding errors after drawing the first sub-triangle)
		void skip(const vertex_type &a_Vertex, float a_Delta){
			m_X = a_Vertex.get_position().m_X + m_Dx * a_Delta;

			if(_Description::m_HasColor){
				m_R = a_Vertex.get_color().m_R + m_Dr * a_Delta;
				m_G = a_Vertex.get_color().m_G + m_Dg * a_Delta;
				m_B = a_Vertex.get_color().m_B + m_Db * a_Delta;
			}
		}
	};
}
}